<template>
  <!-- 遮罩层（带渐变动画） -->
  <transition name="fade">
    <div v-if="isOpen" class="popup-mask" @click.self="closeOnClickOverlay && close()"></div>
  </transition>

  <!-- 弹窗内容（底部弹出动画） -->
  <transition name="slide-up">
    <div v-if="isOpen" class="popup-container" :style="{
      height,
    }">
      <!-- 顶部拖动条（仅底部弹出显示） -->
      <div v-if="showDragHandle" class="drag-handle" @click="() => close()"></div>

      <!-- 内容区域（支持插槽） -->
      <div class="popup-content">
        <slot></slot>
      </div>
    </div>
  </transition>
</template>

<script setup>
import { ref, computed, watch } from 'vue'

const props = defineProps({
  // 控制弹窗显示（v-model）
  modelValue: Boolean,

  // 弹出位置（默认底部）
  position: {
    type: String,
    default: 'bottom',
    validator: v => ['top', 'bottom', 'left', 'right'].includes(v)
  },

  // 弹窗高度（默认100%）
  height: {
    type: String,
    default: '100%'
  },

  // 点击遮罩是否关闭
  closeOnClickOverlay: {
    type: Boolean,
    default: true
  }
})

const emit = defineEmits(['update:modelValue', 'open', 'close'])

// 组件内部状态
const isOpen = ref(false)

// 是否显示顶部拖动条（仅底部弹出时显示）
const showDragHandle = computed(() => props.position === 'bottom')

// 监听v-model变化
watch(() => props.modelValue, val => {
  isOpen.value = val
  val ? emit('open') : emit('close')
})

// 打开弹窗
const open = () => {
  isOpen.value = true
  emit('update:modelValue', true)
}

// 关闭弹窗（带动画）
const close = () => {
  isOpen.value = false
  emit('update:modelValue', false)
}

// 暴露方法给父组件
defineExpose({ open, close })
</script>

<style scoped>
/* 遮罩层样式 */
.popup-mask {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  z-index: 999;
}

/* 弹窗容器 */
.popup-container {
  position: fixed;
  left: 0;
  width: 100%;
  background: white;
  z-index: 1000;
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
}

/* 底部定位 */
.popup-container {
  bottom: 0;
}

/* 顶部拖动条样式 */
.drag-handle {
  position: absolute;
  left: calc(50% - 20px);
  width: 40px;
  height: 10px;
  border-top: 4px solid #e8e8e8;
  border-radius: 2px;
  margin: 5px auto;
}

/* 内容区域（可滚动） */
.popup-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 1;
  overflow-y: auto;
  padding: 16px;
}

/* 遮罩渐变动画 */
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

/* 底部弹出动画 */
.slide-up-enter-active,
.slide-up-leave-active {
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.slide-up-enter-from,
.slide-up-leave-to {
  transform: translateY(100%);
}
</style>